/****************************************************
	文件：SceneMgr.cs
	作者：HuskyT
	邮箱：1005240602@qq.com
	日期：2020/10/4 21:12:9
	功能：场景管理器（处理场景跳转）
*****************************************************/

using System;
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
using HTUtility;
using HTFramework.ResKit;
using HTDemo01;

namespace HTFramework.UIKit
{
    public class SceneMgr : Singleton<SceneMgr>
    {
        /// <summary>
        /// 开始加载场景的回调
        /// </summary>
        private Action mOnLoadSceneEnterCallBack;
        /// <summary>
        /// 加载场景中的回调
        /// </summary>
        private Action mOnLoadSceneMidCallBack;
        /// <summary>
        /// 场景加载完成时的回调
        /// </summary>
        private Action mOnLoadSceneOverCallBack;

        /// <summary>
        /// 当前场景名
        /// </summary>
        public string CurrentScene { get; set; }
        /// <summary>
        /// 场景加载完成的标志位
        /// </summary>
        public bool IsAlreadyLoaded { get; set; }
        /// <summary>
        /// 加载场景进度（max num：100）
        /// </summary>
        public int LoadProgress { get; set; }

        /// <summary>
        /// 用于异步加载场景的 MonoBehaviour
        /// </summary>
        private MonoBehaviour mMono;

        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="mono">用于异步加载场景的 MonoBehaviour</param>
        public void Init(MonoBehaviour mono)
        {
            mMono = mono;
            HTLogger.Info("SceneMgr init done.");
        }
        /// <summary>
        /// 设置场景配置
        /// </summary>
        /// <param name="sceneName">场景名</param>
        public void SetSceneSetting(string sceneName)
        {
            HTLogger.Debug("设置 {0} 场景配置", sceneName);
            //TODO 设置场景配置
        }
        /// <summary>
        /// 加载场景
        /// </summary>
        /// <param name="sceneName">场景名</param>
        public void LoadScene(string sceneName)
        {
            LoadProgress = 0;
            UIMgr.Instance.CloseAllWnd();
            UIMgr.Instance.OpenWnd(GConsts.LOADING_PANEL);
            mMono.StartCoroutine(AsyncLoadScene(sceneName));
        }

        private IEnumerator AsyncLoadScene(string sceneName)
        {
            IsAlreadyLoaded = false;
            ClearCache(); //清空缓存资源
            mOnLoadSceneEnterCallBack?.Invoke();
            //跳转到 Loading 界面
            AsyncOperation loadingScene = SceneManager.LoadSceneAsync(FConsts.LOADING_SCENE, LoadSceneMode.Single);
            while (loadingScene != null && loadingScene.isDone == false)
            {
                yield return new WaitForEndOfFrame();
            }
            //跳转到新场景
            int targetProgress = 0;
            AsyncOperation newScene = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Single);
            if (newScene != null && newScene.isDone == false)
            {
                newScene.allowSceneActivation = false; //加载的时候不显示新场景
                //先加载30%
                if (newScene.progress <= 0.3f)
                {
                    targetProgress = (int)(newScene.progress * 100);
                    while (LoadProgress <= targetProgress)
                    {
                        LoadProgress++;
                        yield return new WaitForEndOfFrame();
                    }
                }
                //执行场景加载中的回调
                mOnLoadSceneMidCallBack?.Invoke();
                //加载到90%
                if (newScene.progress <= 0.9f)
                {
                    targetProgress = (int)(newScene.progress * 100);
                    while (LoadProgress <= targetProgress)
                    {
                        LoadProgress++;
                        yield return new WaitForEndOfFrame();
                    }
                }
                CurrentScene = sceneName;
                SetSceneSetting(sceneName);
                //再加载剩余10%（这一部分Unity执行非常快，所以自行模拟平滑加载）
                targetProgress = 100;
                while (LoadProgress <= targetProgress - 2)
                {
                    LoadProgress++;
                    yield return new WaitForEndOfFrame();
                }
                LoadProgress = targetProgress;
                newScene.allowSceneActivation = true; //加载完成显示新场景
                IsAlreadyLoaded = true;
                mOnLoadSceneOverCallBack?.Invoke();
                UnsubscribeAllCallBack();
            }
        }

        /// <summary>
        /// 注册 切换场景 Enter 回调
        /// </summary>
        /// <param name="loadSceneEnter"></param>
        public void SubscribeOnLoadSceneEnterCallBack(Action loadSceneEnter)
        {
            mOnLoadSceneEnterCallBack += loadSceneEnter;
        }
        /// <summary>
        /// 注册 切换场景 Mid 回调
        /// </summary>
        /// <param name="loadSceneMid"></param>
        public void SubscribeOnLoadSceneMidCallBack(Action loadSceneMid)
        {
            mOnLoadSceneMidCallBack += loadSceneMid;
        }
        /// <summary>
        /// 注册 切换场景 Over 回调
        /// </summary>
        /// <param name="loadSceneOver"></param>
        public void SubscribeOnLoadSceneOverCallBack(Action loadSceneOver)
        {
            mOnLoadSceneOverCallBack += loadSceneOver;
        }
        /// <summary>
        /// 注销所有回调
        /// </summary>
        public void UnsubscribeAllCallBack()
        {
            mOnLoadSceneEnterCallBack = null;
            mOnLoadSceneOverCallBack = null;
            mOnLoadSceneMidCallBack = null;
        }

        /// <summary>
        /// 清除缓存资源
        /// </summary>
        private void ClearCache()
        {
            HTLogger.Debug("加载场景时，清空缓存资源");
            //TODO：跳转场景时，清空缓存资源
        }
    }
}
